package com.wenhai.io;

import cn.hutool.core.util.CharsetUtil;

import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.CharBuffer;
import java.nio.IntBuffer;
import java.nio.charset.Charset;
import java.util.Arrays;

/**
 * {@link ByteBuffer} 方法示例
 *
 * @author wenhai
 * @date 2020/11/2
 */
public class ByteBufferDemo {
    public static void main(String[] args) throws UnsupportedEncodingException {
        // wrapMethod();
//        putAndGetMethod();
//        bulkPutOrGetMethod();
//        getOrPutIndexMethod();
//        getTypeMethod();
//        sliceMethod();
//        asCharBufferMethod();
//        decodeByteBufferMethod();
//        orderMethod();
//        orderErrorResult();
        compactMethod();

    }

    private static void compactMethod() {
        byte[] bytes = {1, 2, 3, 4, 5, 6};
        ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
        System.out.println("A capacity = " + byteBuffer.capacity() + " , position = " + byteBuffer.position() + " , limit = " + byteBuffer.limit());
        System.out.println("1 getValue = " + byteBuffer.get());
        System.out.println("B capacity = " + byteBuffer.capacity() + " , position = " + byteBuffer.position() + " , limit = " + byteBuffer.limit());
        System.out.println("2 getValue = " + byteBuffer.get());
        System.out.println("C capacity = " + byteBuffer.capacity() + " , position = " + byteBuffer.position() + " , limit = " + byteBuffer.limit());
        byteBuffer.compact();
        System.out.println("byteBuffer.compact()");
        System.out.println("D capacity = " + byteBuffer.capacity() + " , position = " + byteBuffer.position() + " , limit = " + byteBuffer.limit());
        System.out.println(Arrays.toString(byteBuffer.array()));

    }

    private static void orderErrorResult() {
        ByteBuffer bb = ByteBuffer.allocate(8);
        bb.order(ByteOrder.BIG_ENDIAN);
        bb.putInt(123);
        bb.putInt(567);
        bb.flip();
        System.out.println(bb.getInt());
        System.out.println(bb.getInt());
        ByteBuffer bb2 = ByteBuffer.wrap(bb.array());
        bb2.order(ByteOrder.LITTLE_ENDIAN);
        System.out.println(bb2.getInt());
        System.out.println(bb2.getInt());
    }

    private static void orderMethod() {
        int value = 123456789;
        ByteBuffer bb = ByteBuffer.allocate(4);
        System.out.print(bb.order() + " ");
        System.out.print(bb.order() + " ");
        bb.putInt(value);
        byte[] bytes = bb.array();
        System.out.println(Arrays.toString(bytes));
        bb = ByteBuffer.allocate(4);
        System.out.print(bb.order() + " ");
        bb.order(ByteOrder.BIG_ENDIAN);
        System.out.print(bb.order() + " ");
        bb.putInt(value);
        bytes = bb.array();
        System.out.println(Arrays.toString(bytes));

        bb = ByteBuffer.allocate(4);
        System.out.print(bb.order() + " ");
        bb.order(ByteOrder.LITTLE_ENDIAN);
        System.out.print(bb.order() + " ");
        bb.putInt(value);
        bytes = bb.array();
        System.out.println(Arrays.toString(bytes));

    }

    private static void decodeByteBufferMethod() throws UnsupportedEncodingException {
        byte[] bytes = "我是中国人".getBytes(CharsetUtil.defaultCharsetName());
        ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
        CharBuffer charBuffer = Charset.forName("UTF-8").decode(byteBuffer);
        for (int i = 0; i < charBuffer.limit(); i++) {
            System.out.print(charBuffer.get() + " ");
        }
    }

    private static void asCharBufferMethod() throws UnsupportedEncodingException {
        byte[] bytes = "我是中国人".getBytes("utf-16BE");
        System.out.println(Charset.defaultCharset().name());
        ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
        System.out.println("byteBuffer = " + byteBuffer.getClass().getName());
        CharBuffer charBuffer = byteBuffer.asCharBuffer();
        System.out.println("charBuffer = " + charBuffer.getClass().getName());
        System.out.println("charBuffer.position = " + byteBuffer.position() + " , byteBuffer.capacity = " + byteBuffer.capacity() + " , byteBuffer.limit = " + byteBuffer.limit());
        System.out.println("charBuffer.position = " + charBuffer.position() + " , charBuffer.capacity = " + charBuffer.capacity() + " , charBuffer.limit = " + charBuffer.limit());
        System.out.println(charBuffer.capacity());
        charBuffer.position(0);
        for (int i = 0; i < charBuffer.capacity(); i++) {
            System.out.print(charBuffer.get() + " ");
        }
        System.out.println();
    }

    private static void sliceMethod() {
        byte[] byteArray = {1, 2, 3, 4, 5, 6};
        ByteBuffer byteBuffer = ByteBuffer.wrap(byteArray);
        byteBuffer.position(2);
        System.out.println("byteBuffer.remaining = " + byteBuffer.remaining());
        ByteBuffer slice = byteBuffer.slice();
        System.out.println("slice.position = " + slice.position() + " capacity = " + slice.capacity() + " , limit = " + slice.limit());
        for (int i = 0; i < slice.limit(); i++) {
            System.out.print(slice.get() + " ");
        }

    }

    private static void getTypeMethod() {
        ByteBuffer byteBuffer = ByteBuffer.allocate(100);
        byteBuffer.putLong(1L);
        byteBuffer.putInt(10);
        System.out.println(byteBuffer.getLong(0));
        System.out.println(byteBuffer.getInt(8));

        ByteBuffer buffer = ByteBuffer.allocate(10);
        System.out.println("A1 = " + buffer.position());
        buffer.putInt(123);
        System.out.println("A2 = " + buffer.position());
        buffer.putInt(456);
        System.out.println("A3 = " + buffer.position());
        IntBuffer intBuffer = IntBuffer.allocate(10);
        System.out.println("B1 = " + intBuffer.position());
        intBuffer.put(456);
        System.out.println("B2 = " + intBuffer.position());
        intBuffer.put(789);
        System.out.println("B3 = " + intBuffer.position());


        ByteBuffer bb = ByteBuffer.allocate(10);

        bb.putInt(123);
        bb.putInt(456);
        bb.flip();
        System.out.println("bb.position = " + bb.position() + ", value = " + bb.getInt());
        System.out.println("bb.position = " + bb.position() + ", value = " + bb.getInt());
        System.out.println("bb.position = " + bb.position());
        IntBuffer ib = IntBuffer.allocate(10);
        ib.put(456);
        ib.put(789);
        ib.flip();
        System.out.println("ib.position = " + ib.position() + ", value = " + ib.get());
        System.out.println("ib.position = " + ib.position() + ", value = " + ib.get());
        System.out.println("ib.position = " + ib.position());

    }

    private static void getOrPutIndexMethod() {
        byte[] byteArray = {1, 2, 3, 4, 5, 6};
        ByteBuffer byteBuffer = ByteBuffer.wrap(byteArray);
        System.out.println("position = " + byteBuffer.position());
        System.out.println(byteBuffer.get(1));
        System.out.println("position = " + byteBuffer.position());
        byteBuffer.put(1, (byte) 1);
        System.out.println("position = " + byteBuffer.position());
        System.out.println(byteBuffer.get(1));
    }

    private static void bulkPutOrGetMethod() {
        byte[] byteArrayIn1 = {1, 2, 3, 4, 5, 6, 7, 8};
        byte[] byteArrayIn2 = {55, 66, 77, 88};
        ByteBuffer byteBuffer = ByteBuffer.allocate(10);
        byteBuffer.put(byteArrayIn1);
        byteBuffer.position(2);
        byteBuffer.put(byteArrayIn2, 1, 3);
        System.out.print("A = ");
        byte[] getByte = byteBuffer.array();
        System.out.println(Arrays.toString(getByte));
        byteBuffer.position(1);
        byte[] byteArrayOut = new byte[byteBuffer.capacity()];
        byteBuffer.get(byteArrayOut, 3, 4);
        System.out.print("B  = ");
        System.out.println(Arrays.toString(byteArrayOut));

    }

    private static void putAndGetMethod() {

    }

    private static void wrapMethod() {
        byte[] byteArray = {1, 2, 3, 4, 5, 6, 7, 8};
        ByteBuffer byteBuffer = ByteBuffer.wrap(byteArray);
        ByteBuffer rangeByteBuffer = ByteBuffer.wrap(byteArray, 2, 4);
        System.out.println("byteBuffer capacity = " + byteBuffer.capacity() + " , limit = " + byteBuffer.limit()
                + " , position = " + byteBuffer.position());
        System.out.println("rangeByteBuffer capacity = " + rangeByteBuffer.capacity()
                + " , limit = " + rangeByteBuffer.limit() + " , position = " + rangeByteBuffer.position());
    }
}
